using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using common = Microsoft.ConnectionEngine.Common;
using dao = Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common;
using Microsoft.ConnectionEngine.Common.Security;
using Microsoft.ConnectionEngine.Registers.Health.Patient;

namespace Microsoft.ConnectionEngine.Registers.Health.Patient.Business
{
    /// <summary>
    /// Provider helper methods to access a adapter and evaluate Connection Engine Message payload responses.
    /// </summary>
    public class AdapterHelper
    {
        private static SystemAdapter adapter;

        /// <summary>
        /// The Adapter used by the adapter helper.
        /// </summary>
        internal static SystemAdapter PatientRegisterAdapter
        {
            get
            {
                if (adapter == null)
                    adapter = new SystemAdapter();
                return adapter;
            }
        }

        /// <summary>
        /// A proxy call to Adapter's SendConnectionEngineMessage.
        /// </summary>
        /// <param name="messagetypeID">Idnetifies the type of message being sent.</param>
        /// <param name="destinationID">The unique identifier of the destination Connected System.</param>
        /// <param name="payload">The content of the message being sent.</param>
        /// <returns></returns>
        internal static common.ConnectionEngineMessage SendConnectionEngineMessage(int messagetypeID, string destinationID, string payload)
        {
            return PatientRegisterAdapter.SendConnectionEngineMessage(payload, messagetypeID, destinationID);
        }

        /// <summary>
        /// Returns an object based on a Connection Engine Message payload and a object type.
        /// </summary>
        /// <param name="response">The Connection Engine Message that contains the payload to be deserialized.</param>
        /// <param name="type">The type of object the payload represents.</param>
        /// <returns>Returns an object representation of the payload.</returns>
        internal static object GetPayloadObjectFromResponse(common.ConnectionEngineMessage response, Type type)
        {
            // Can't checkout 
            if (response.Header.Status.Code == 9)
                return null;

            if (response.Header.Status.Code != 0)
                throw new Exception(response.Header.Status.Description);

            if (response.Body.Payload.Content != string.Empty)
                return common.Utilities.DeserializeObject(response.Body.Payload.Content, type);

            else
                return null;
        }

        
        /// <summary>
        /// Evaluates the Connection Engine Message and return a boolean if the message was successfully acknowledged.
        /// </summary>
        /// <param name="response">The Connection Engine Message was successfully acknowledged.</returns>
        internal static bool GetBooleanFromResponse(common.ConnectionEngineMessage response)
        {
            // Can't checkout 
            if (response.Header.Status.Code == 9)
                return false;

            if (response.Header.Status.Code != 0)
                throw new Exception(response.Header.Status.Description);

            return true;
        }
        
        [Obsolete("Should be using \"Microsoft.ConnectionEngine.Common.Utilities.SerializeObject\" instead")]
        public static string Serialise(object content, Type contentType)
        {
            System.Text.StringBuilder doc = new System.Text.StringBuilder();

            XmlSerializer serializer = new XmlSerializer(contentType);
            System.IO.TextWriter tw = new System.IO.StringWriter(doc);
            serializer.Serialize(tw, content);
            tw.Close();
            return doc.ToString();
        }

        /// <summary>
        /// Creates a Connection Engine Message payload based on the arguments passed as parameters.
        /// </summary>
        /// <param name="principal">The credentials of the user requesting the service.</param>
        /// <param name="rootElement">A string representing the name of the xml's root element.</param>
        public static string ConstructPayloadXml(HSDPrincipal principal, string rootElement, string content)
        {
            string payload = 
                String.Format(@"<request xmlns=""http://Microsoft.ConnectionEngine/Schemas/ServiceProviderRegister"">{0}<{1}>{2}</{1}></request>",
                SecurityManager.ConstructUserCredentialsXml(principal), rootElement, content);
            return payload;
        }

        /// <summary>
        /// Creates a Connection Engine Message payload based on the arguments passed as parameters.
        /// </summary>
        /// <param name="principal">The credentials of the user requesting the service.</param>
        public static string ConstructPayloadXml(HSDPrincipal principal, string content)
        {
            string payload =
                String.Format(@"<request xmlns=""http://Microsoft.ConnectionEngine/Schemas/ServiceProviderRegister"">{0}{1}</request>",
                SecurityManager.ConstructUserCredentialsXml(principal), content);
            return payload;
        }

        /// <summary>
        /// Gets the unique identifier of a messagetype based on its enumeration value.
        /// </summary>
        /// <param name="messageType">The message type in enumeration format.</param>
        /// <returns>Returns an integer representing the unique of the message type.</returns>
        public static int GetMessageTypeValue(dao.MessageTypes messageType)
        {
            return (int) messageType;
        }

        /// <summary>
        /// Gets the unique identifier of a messagetype based on its enumeration value.
        /// </summary>
        /// <param name="messageType">The message type in enumeration format.</param>
        /// <returns>Returns a string representing the unique of the message type.</returns>
        public static string GetMessageTypeNumber(dao.MessageTypes messageType)
        {
            return Enum.Format(typeof(dao.MessageTypes), messageType, "d").ToString();
        }

        
        [Obsolete("Should be using \"Microsoft.ConnectionEngine.Common.Utilities.SerializeObject\" instead")]
        public static string ConstructObjectXml(object content, Type contentType)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(contentType);
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                System.IO.StringWriter sw = new System.IO.StringWriter(sb);
                System.Xml.XmlTextWriter tw = new System.Xml.XmlTextWriter(sw);

                // get rid of xml Processing Instruction declaration
                tw.Formatting = System.Xml.Formatting.None;
                tw.WriteRaw(String.Empty);

                // get rid of xsd/xsi declaraions
                //XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
                //xsn.Add(String.Empty, String.Empty);

                // serialize and return the result
                serializer.Serialize(tw, content);
                return sb.ToString();
            }
            catch (Exception exc)
            {
                throw exc;
            }
            
        }
    }
}
